package com.aegis.manage.service.sys.user;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.StrUtil;
import com.aegis.manage.api.request.UpdateUserProfileRequest;
import com.aegis.manage.api.vo.SysUserVO;
import com.aegis.manage.utils.AuthUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.aegis.common.mybatis.base.BaseDO;
import com.aegis.common.mybatis.base.BaseServiceImpl;
import com.aegis.common.mybatis.constants.DeleteFlagEnum;
import com.aegis.common.mybatis.model.PageResult;
import com.aegis.common.utils.AssertUtil;
import com.aegis.manage.api.request.CreateUserRequest;
import com.aegis.manage.api.request.UpdateUserRequest;
import com.aegis.manage.api.vo.SysRoleVO;
import com.aegis.manage.api.vo.UserDetailVO;
import com.aegis.manage.config.ManageProperties;
import com.aegis.manage.enums.ResponseEnums;
import com.aegis.manage.mapper.SysUserMapper;
import com.aegis.manage.mapper.SysUserRoleMapper;
import com.aegis.manage.model.dos.SysPermission;
import com.aegis.manage.model.dos.SysRole;
import com.aegis.manage.model.dos.SysUser;
import com.aegis.manage.model.dos.SysUserRole;
import com.aegis.manage.service.sys.permission.SysPermissionService;
import com.aegis.manage.service.sys.role.SysRoleService;
import com.aegis.manage.utils.PasswordUtil;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * @Author renogo
 *
 * @Version 1.0
 */
@Slf4j
@Service
public class SysUserServiceImpl extends BaseServiceImpl<SysUserMapper, SysUser> implements SysUserService {

    @Autowired
    private SysPermissionService sysPermissionService;

    @Autowired
    private SysRoleService sysRoleService;

    @Autowired
    private SysUserRoleMapper sysUserRoleMapper;

    @Autowired
    private ManageProperties manageProperties;


    @Override
    public SysUser getUserByUsernameAndPwd(String username, String password) {
        return selectOne(SysUser::getUsername, username,
                SysUser::getPassword, getPasswordInDb(password));
    }

    @Override
    public SysUser getUserByUsername(String username) {
        return selectOne(SysUser::getUsername, username);
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public String createUser(CreateUserRequest createUserRequest) {
        SysUser userDO = getUserByUsername(createUserRequest.getUsername());
        AssertUtil.xAssert(userDO != null, ResponseEnums.ACCOUNT_EXIST);
        userDO = new SysUser();
        userDO.convert(createUserRequest);
        String password = getPasswordInDb(createUserRequest.getPassword());
        userDO.setPassword(password);
        userDO.setDeleteFlag(DeleteFlagEnum.EXIST);
        AssertUtil.xAssert(!userDO.insert(), ResponseEnums.REGISTER_FAIL);
        if (CollectionUtil.isNotEmpty(createUserRequest.getRoleIds())) {
            bindUserRole(userDO.getId(), new HashSet<>(createUserRequest.getRoleIds()));
        }
        return userDO.getId();
    }

    @Override
    public PageResult<SysUserVO> selectUserPage(int current, int size, String keywords) {
        return PageResult.exchange(getBaseMapper().queryUserPage(new Page<>(current, size), keywords));
    }

    @Override
    public void delUser(String userId) {
        AssertUtil.operateFailed("admin".equals(userId), "系统默认用户禁止删除");
        AssertUtil.xAssert(baseMapper.deleteById(userId) <= 0, ResponseEnums.REGISTER_FAIL);
    }

    @Override
    public UserDetailVO getUserDetailById(String userId) {
        SysUser sysUser = baseMapper.selectById(userId);
        if (sysUser == null) {
            return null;
        }
        List<SysPermission> sysPermissions = sysPermissionService.selectUserPermissionByUserId(userId);
        List<SysRole> sysRoles = sysRoleService.selectRoleByUserId(userId);
        UserDetailVO userDetailVO = new UserDetailVO();
        userDetailVO.convert(sysUser);
        if (CollectionUtil.isNotEmpty(sysPermissions)) {
            userDetailVO.setPermissions(sysPermissions
                    .stream()
                    .map(SysPermission::getPermission)
                    .collect(Collectors.toList()));
        }
        if (CollectionUtil.isNotEmpty(sysRoles)) {
            userDetailVO.setRoles(sysRoles.stream().map(sysRoleDO -> {
                SysRoleVO sysRoleVO = new SysRoleVO();
                return (SysRoleVO) sysRoleVO.convert(sysRoleDO);
            }).collect(Collectors.toList()));
        }
        return userDetailVO;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void updateByUserId(UpdateUserRequest updateUserRequest) {
        if (CollUtil.isNotEmpty(updateUserRequest.getRoles())) {
            bindUserRole(updateUserRequest.getId(), new HashSet<>(updateUserRequest.getRoles()));
        }
        String password = getPasswordInDb(updateUserRequest.getPassword());
        SysUser sysUser = new SysUser();
        sysUser.convert(updateUserRequest);
        sysUser.setPassword(password);
        AssertUtil.xAssert(baseMapper.updateById(sysUser) <= 0, ResponseEnums.UPDATE_USER_FAIL);
    }

    @Override
    public void updateUserProfile(UpdateUserProfileRequest updateUserProfileRequest) {
        String newPassword = updateUserProfileRequest.getNewPassword();
        if (StrUtil.isNotBlank(updateUserProfileRequest.getOldPassword())) {
            AssertUtil.operateFailed(StrUtil.isBlank(newPassword),"缺少新密码");
            SysUser sysUser = getUserByUsernameAndPwd(AuthUtil.getLoginUserInfo().getAccount(), updateUserProfileRequest.getOldPassword());
            AssertUtil.operateFailed(sysUser == null, "旧密码错误");
            AssertUtil.operateFailed(sysUser.getPassword().equals(getPasswordInDb(newPassword)), "新密码不能与旧密码相同");
        }
        UpdateUserRequest updateUserRequest = new UpdateUserRequest();
        updateUserRequest.setId(AuthUtil.getLoginUserId());
        updateUserRequest.setPassword(updateUserProfileRequest.getNewPassword());
        updateUserRequest.setNickname(updateUserProfileRequest.getNickname());
        updateByUserId(updateUserRequest);
    }

    @Override
    public void bindUserRole(String userId, Set<String> roleIds) {
        List<SysRole> hasRoleDO = sysRoleService.selectRoleByUserId(userId);
        //需要绑定的角色id
        Collection<String> bindRoleId = null;
        //用户已有角色
        if (CollectionUtil.isNotEmpty(hasRoleDO)) {
            //去重，保留应该绑定的角色权限
            Set<String> collect = hasRoleDO.stream().map(BaseDO::getId).collect(Collectors.toSet());
            bindRoleId = CollectionUtil.subtract(roleIds, collect);
        }
        if (bindRoleId == null) {
            bindRoleId = roleIds;
        }
        sysUserRoleMapper.saveBatch(bindRoleId.stream().map(s -> {
            SysUserRole sysUserRole = new SysUserRole();
            sysUserRole.setRoleId(s);
            sysUserRole.setUserId(userId);
            return sysUserRole;
        }).collect(Collectors.toList()));
    }

    private String getPasswordInDb(String rsaPwd) {
        return PasswordUtil.getPasswordInDb(rsaPwd, manageProperties.getPwdPrivateKey(),
                manageProperties.getPwdSalt());
    }


}
